using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using JGSY.CMS.LowCode.Platform.Application.DTOs;
using JGSY.CMS.LowCode.Platform.Application.Interfaces;
using JGSY.CMS.LowCode.Platform.Domain.Entities;
using JGSY.CMS.LowCode.Platform.Domain.Interfaces;

namespace JGSY.CMS.LowCode.Platform.Application.Services
{
    /// <summary>
    /// 页面应用服务实现
    /// </summary>
    public class PageAppService : IPageAppService
    {
        private readonly IPageRepository _pageRepository;
        private readonly ILogger<PageAppService> _logger;

        public PageAppService(IPageRepository pageRepository, ILogger<PageAppService> logger)
        {
            _pageRepository = pageRepository;
            _logger = logger;
        }
        public async Task<int> BatchDeleteAsync(IEnumerable<long> ids)
        {
            try
            {
                _logger.LogInformation("开始批量删除页面，IDs: {Ids}", string.Join(",", ids));
                
                var result = await _pageRepository.BatchDeleteAsync(ids);
                
                _logger.LogInformation("成功批量删除 {Count} 个页面", result);
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量删除页面失败，IDs: {Ids}", string.Join(",", ids));
                throw;
            }
        }

        public async Task<PageDto> CreateAsync(PageDto pageDto)
        {
            try
            {
                _logger.LogInformation("开始创建页面: {Title}", pageDto.Title);

                // 检查别名是否已存在
                if (!string.IsNullOrEmpty(pageDto.Slug))
                {
                    var slugExists = await _pageRepository.SlugExistsAsync(pageDto.Slug);
                    if (slugExists)
                    {
                        throw new InvalidOperationException($"页面别名 '{pageDto.Slug}' 已存在");
                    }
                }

                var page = new Page
                {
                    Title = pageDto.Title,
                    Slug = pageDto.Slug ?? GenerateSlugFromTitle(pageDto.Title),
                    ParentId = pageDto.ParentId,
                    TemplateId = pageDto.TemplateId,
                    Content = pageDto.Content,
                    Description = pageDto.Description,
                    Tags = pageDto.Tags,
                    SeoTitle = pageDto.SeoTitle,
                    SeoKeywords = pageDto.SeoKeywords,
                    SeoDescription = pageDto.SeoDescription,
                    CustomFields = pageDto.CustomFields,
                    SortOrder = pageDto.SortOrder,
                    ShowInNavigation = pageDto.ShowInNavigation,
                    Status = pageDto.Status,
                    Version = 1,
                    CreatedBy = pageDto.CreatedBy,
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow
                };

                await _pageRepository.AddAsync(page);
                
                _logger.LogInformation("成功创建页面: {Title}, ID: {Id}", page.Title, page.Id);
                return MapToDto(page);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "创建页面失败: {Title}", pageDto.Title);
                throw;
            }
        }

        public async Task<bool> DeleteAsync(long id)
        {
            try
            {
                _logger.LogInformation("开始删除页面，ID: {Id}", id);

                // 检查页面是否存在
                var page = await _pageRepository.GetByIdAsync(id);
                if (page == null)
                {
                    _logger.LogWarning("删除失败：页面不存在，ID: {Id}", id);
                    return false;
                }

                // 检查是否有子页面
                var children = await _pageRepository.GetChildrenAsync(id);
                if (children.Any())
                {
                    throw new InvalidOperationException("不能删除包含子页面的页面，请先删除或移动子页面");
                }

                await _pageRepository.DeleteAsync(id);
                
                _logger.LogInformation("成功删除页面，ID: {Id}", id);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除页面失败，ID: {Id}", id);
                throw;
            }
        }

        public async Task<IEnumerable<PageDto>> GetAllAsync()
        {
            try
            {
                _logger.LogInformation("获取所有页面");
                
                var pages = await _pageRepository.GetAllAsync();
                return pages.Select(MapToDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取所有页面失败");
                throw;
            }
        }

        public async Task<PageDto?> GetByIdAsync(long id)
        {
            try
            {
                _logger.LogInformation("根据ID获取页面：{Id}", id);
                
                var page = await _pageRepository.GetByIdAsync(id);
                return page == null ? null : MapToDto(page);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "根据ID获取页面失败：{Id}", id);
                throw;
            }
        }

        public async Task<PageDto?> GetBySlugAsync(string slug)
        {
            try
            {
                _logger.LogInformation("根据别名获取页面：{Slug}", slug);
                
                var page = await _pageRepository.GetBySlugAsync(slug);
                return page == null ? null : MapToDto(page);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "根据别名获取页面失败：{Slug}", slug);
                throw;
            }
        }

        public async Task<IEnumerable<PageDto>> GetChildrenAsync(long parentId)
        {
            try
            {
                _logger.LogInformation("获取子页面，父页面ID：{ParentId}", parentId);
                
                var children = await _pageRepository.GetChildrenAsync(parentId);
                return children.Select(MapToDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取子页面失败，父页面ID：{ParentId}", parentId);
                throw;
            }
        }

        public async Task<IEnumerable<PageDto>> GetHierarchyAsync()
        {
            try
            {
                _logger.LogInformation("获取页面层级结构");
                
                var pages = await _pageRepository.GetHierarchyAsync();
                return pages.Select(MapToDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取页面层级结构失败");
                throw;
            }
        }

        public async Task<IEnumerable<PageDto>> GetNavigationPagesAsync()
        {
            try
            {
                _logger.LogInformation("获取导航页面");
                
                var pages = await _pageRepository.GetNavigationPagesAsync();
                return pages.Select(MapToDto);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取导航页面失败");
                throw;
            }
        }

        public async Task<(IEnumerable<PageDto> Items, int TotalCount)> GetPagedAsync(int pageIndex, int pageSize, string? keyword = null, byte? status = null)
        {
            try
            {
                _logger.LogInformation("分页获取页面列表，页码：{PageIndex}，页大小：{PageSize}，关键词：{Keyword}，状态：{Status}", 
                    pageIndex, pageSize, keyword, status);
                
                var result = await _pageRepository.GetPagedAsync(pageIndex, pageSize, keyword, status);
                var items = result.Items.Select(MapToDto);
                
                return (items, result.TotalCount);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "分页获取页面列表失败，页码：{PageIndex}，页大小：{PageSize}", pageIndex, pageSize);
                throw;
            }
        }

        public async Task<bool> IncrementViewCountAsync(long id)
        {
            try
            {
                _logger.LogInformation("增加页面访问量，ID：{Id}", id);
                
                var result = await _pageRepository.IncrementViewCountAsync(id);
                
                if (result)
                {
                    _logger.LogInformation("成功增加页面访问量，ID：{Id}", id);
                }
                else
                {
                    _logger.LogWarning("页面不存在，无法增加访问量，ID：{Id}", id);
                }
                
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "增加页面访问量失败，ID：{Id}", id);
                throw;
            }
        }

        public async Task<bool> SlugExistsAsync(string slug, long? excludeId = null)
        {
            try
            {
                _logger.LogInformation("检查页面别名是否存在：{Slug}，排除ID：{ExcludeId}", slug, excludeId);
                
                var exists = await _pageRepository.SlugExistsAsync(slug, excludeId);
                
                _logger.LogInformation("页面别名 {Slug} 存在性检查结果：{Exists}", slug, exists);
                return exists;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "检查页面别名失败：{Slug}", slug);
                throw;
            }
        }

        public async Task<PageDto> UpdateAsync(PageDto pageDto)
        {
            try
            {
                _logger.LogInformation("开始更新页面：{Title}，ID：{Id}", pageDto.Title, pageDto.Id);

                // 检查页面是否存在
                var existingPage = await _pageRepository.GetByIdAsync(pageDto.Id);
                if (existingPage == null)
                {
                    throw new InvalidOperationException($"页面不存在，ID: {pageDto.Id}");
                }

                // 检查别名是否已被其他页面使用
                if (!string.IsNullOrEmpty(pageDto.Slug) && pageDto.Slug != existingPage.Slug)
                {
                    var slugExists = await _pageRepository.SlugExistsAsync(pageDto.Slug, pageDto.Id);
                    if (slugExists)
                    {
                        throw new InvalidOperationException($"页面别名 '{pageDto.Slug}' 已存在");
                    }
                }

                // 更新页面信息
                existingPage.Title = pageDto.Title;
                existingPage.Slug = pageDto.Slug ?? existingPage.Slug;
                existingPage.ParentId = pageDto.ParentId;
                existingPage.TemplateId = pageDto.TemplateId;
                existingPage.Content = pageDto.Content;
                existingPage.Description = pageDto.Description;
                existingPage.Tags = pageDto.Tags;
                existingPage.SeoTitle = pageDto.SeoTitle;
                existingPage.SeoKeywords = pageDto.SeoKeywords;
                existingPage.SeoDescription = pageDto.SeoDescription;
                existingPage.CustomFields = pageDto.CustomFields;
                existingPage.SortOrder = pageDto.SortOrder;
                existingPage.ShowInNavigation = pageDto.ShowInNavigation;
                existingPage.Status = pageDto.Status;
                existingPage.UpdatedBy = pageDto.UpdatedBy;
                existingPage.UpdatedAt = DateTime.UtcNow;
                existingPage.Version += 1; // 增加版本号

                await _pageRepository.UpdateAsync(existingPage);
                
                _logger.LogInformation("成功更新页面：{Title}，ID：{Id}", existingPage.Title, existingPage.Id);
                return MapToDto(existingPage);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新页面失败：{Title}，ID：{Id}", pageDto.Title, pageDto.Id);
                throw;
            }
        }

        public async Task<bool> UpdateStatusAsync(long id, byte status)
        {
            try
            {
                _logger.LogInformation("更新页面状态，ID：{Id}，状态：{Status}", id, status);

                // 检查页面是否存在
                var page = await _pageRepository.GetByIdAsync(id);
                if (page == null)
                {
                    _logger.LogWarning("更新状态失败：页面不存在，ID：{Id}", id);
                    return false;
                }

                page.Status = status;
                page.UpdatedAt = DateTime.UtcNow;

                await _pageRepository.UpdateAsync(page);
                
                _logger.LogInformation("成功更新页面状态，ID：{Id}，状态：{Status}", id, status);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "更新页面状态失败，ID：{Id}，状态：{Status}", id, status);
                throw;
            }
        }

        /// <summary>
        /// 将Page实体映射为PageDto
        /// </summary>
        /// <param name="page">Page实体</param>
        /// <returns>PageDto对象</returns>
        private PageDto MapToDto(Page page)
        {
            return new PageDto
            {
                Id = page.Id,
                Title = page.Title,
                Slug = page.Slug,
                ParentId = page.ParentId,
                TemplateId = page.TemplateId,
                Content = page.Content,
                Description = page.Description,
                Tags = page.Tags,
                SeoTitle = page.SeoTitle,
                SeoKeywords = page.SeoKeywords,
                SeoDescription = page.SeoDescription,
                CustomFields = page.CustomFields,
                SortOrder = page.SortOrder,
                ViewCount = page.ViewCount,
                ShowInNavigation = page.ShowInNavigation,
                Status = page.Status,
                Version = page.Version,
                CreatedBy = page.CreatedBy,
                UpdatedBy = page.UpdatedBy,
                CreatedAt = page.CreatedAt,
                UpdatedAt = page.UpdatedAt,
                CreatorName = page.Creator?.RealName ?? page.Creator?.Username,
                UpdaterName = page.Updater?.RealName ?? page.Updater?.Username,
                ParentTitle = page.Parent?.Title,
                TemplateName = page.Template?.Name
            };
        }

        /// <summary>
        /// 根据标题生成URL别名
        /// </summary>
        /// <param name="title">标题</param>
        /// <returns>URL别名</returns>
        private string GenerateSlugFromTitle(string title)
        {
            if (string.IsNullOrEmpty(title))
                return Guid.NewGuid().ToString("N")[..8];

            // 简单的slug生成逻辑，实际项目中可能需要更复杂的处理
            return title.ToLower()
                       .Replace(" ", "-")
                       .Replace("，", "-")
                       .Replace("。", "")
                       .Replace("？", "")
                       .Replace("！", "")
                       .Replace("（", "")
                       .Replace("）", "")
                       .Replace("(", "")
                       .Replace(")", "")
                       .Trim('-');
        }
    }
}
